package sort.tool;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.concurrent.ThreadLocalRandom;

/**
 * 排序的辅助类
 * 生成测试数组，并对排序算法进行测试
 */
public class SortHelper {
    /**
     * 获取随机数对象
     */
    // 不能自己创建ThreadLocalRandom实例，因为它的构造函数是私有的，可以使用它的静态工厂ThreadLocalRandom.current()
    private static final ThreadLocalRandom random = ThreadLocalRandom.current();  // 保证不在多线程之间共享ThreadLocalRandom
    // 以线程维护的实例字段 threadLocalRandomSeed 为种子生成下一个随机数和下一个种子值

    /**
     * 生成一个长度为len且元素范围再[left,right)区间上的随机数组
     * @param len
     * @param left (inclusive)
     * @param right (exclusive)
     * @return
     */
    public static int[] generateRandomArray(int len, int left, int right) {
        int[] nums = new int[len];
        for (int i = 0; i < len; i++) {
            nums[i] = random.nextInt(left, right);
        }
        return nums;
    }

    /**
     * 生成一个近乎有序的、长度为len的数组
     * @param len
     * @param times 交换的次数（交换次数越小，生成的数组越有序）
     * @return
     */
    public static int[] generateSortedArray(int len, int times) {
        int start = random.nextInt(); // 设置起始数
        int[] nums = new int[len];
        nums[0] = start;
        for (int i = 1; i < len; i++) {
            nums[i] = nums[i - 1] + 1;
        }
        for (int i = 0; i < times; i++) {
            // 设置交换的随机索引
            int index1 = random.nextInt(len);
            int index2 = random.nextInt(len);
            int tmp = nums[index1];
            nums[index1] = nums[index2];
            nums[index2] = tmp;
        }
        return nums;
    }

    /**
     * 判断数组是否升序排序
     * @param arr
     * @return
     */
    public static boolean isSorted(int[] arr) {
        for (int i = 0; i < arr.length - 1; i++) {
            if (arr[i] > arr[i + 1]) {
                System.out.println("未排序成功！");
                return false;
            }
        }
        return true;
    }

    /**
     * 根据传入的排序方法对数组arr进行排序
     * @param sortName
     * @param arr
     */
    public static void testSort(String sortName, int[] arr) {
        Class<SevenSort> cls = SevenSort.class;
        try {
            Method method = cls.getDeclaredMethod(sortName, int[].class);
            // 开始时间
            long start = System.nanoTime(); // 纳秒 1ms = 1000000ns
            method.invoke(null, arr);
            long end = System.nanoTime();
            if (isSorted(arr)) {
                System.out.println(sortName + "排序结束共耗时：" + (end - start) / 1000000 + "ms");
            }
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
    }

    /**
     * 生成一个arr的深拷贝数组，用于排序算法性能的比较
     * @param arr
     * @return
     */
    public static int[] copyArray(int[] arr) {
        return Arrays.copyOf(arr, arr.length);
    }

}
